package se.ramfelt.psnfriends.model.web;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.xml.sax.SAXException;

import se.ramfelt.psnfriends.R;
import se.ramfelt.psnfriends.model.Friend;

public class PsnCommunicator implements Runnable {
    private final PlaystationNetwork network;
    private final Listener listener;
    
    public PsnCommunicator(PlaystationNetwork network, Listener listener) {
        this.network = network;
        this.listener = listener;
    }

    public void run() {
        try {			
            listener.onStarted(this);
            List<Friend> friends;
            try {
                friends = retrieveFriends(false);
            } catch (FriendListRetrievalException e) {
                friends = retrieveFriends(true);
            }
            listener.onFinished(this, friends);
        } catch (UnknownHostException e) {
            listener.onError(this, R.string.status_psn_unknown_host, e);
        } catch (UnauthorizedResponseException e) {
    		listener.onError(this, R.string.status_psn_login_error, e);
        } catch (ForbiddenResponseException e) {
    		listener.onError(this, R.string.status_psn_server_forbidden, e);
        } catch (BadRequestResponseException e) {
    		listener.onError(this, R.string.status_psn_server_bad_request, e);
        } catch (FriendListRetrievalException e) {
    		listener.onError(this, R.string.status_psn_server_forbidden, e);
        } catch (UnexpectedResponseCodeException e) {
        	listener.onError(this, R.string.status_psn_unexpected_error, e);
        } catch (Exception e) {
            listener.onError(this, R.string.status_psn_unexpected_error, e); 
        }
    }

    private List<Friend> retrieveFriends(boolean forceLogin) throws MalformedURLException, IOException,
            SAXException, ParserConfigurationException, UnexpectedResponseCodeException, 
            UnauthorizedResponseException, ForbiddenResponseException, BadRequestResponseException, FriendListRetrievalException {
        if (forceLogin || !network.isLoggedIn()) {
            listener.onStatus(this, R.string.status_psn_login);
            network.login();
            listener.onStatus(this, R.string.status_psn_loggedin);
        }
        listener.onStatus(this, R.string.status_psn_getfriendsxml);
        HttpEntity entity = network.getFriendListXml();
        listener.onStatus(this, R.string.status_psn_parsefriendsxml);
        InputStreamReader reader = new InputStreamReader(entity.getContent());
		List<Friend> friends = new FriendListXmlParser().parse(reader);
        entity.consumeContent();
        reader.close();
        listener.onStatus(this, R.string.status_psn_finished);
        return friends;
    }

    public interface Listener {
        void onStarted(PsnCommunicator source);
        void onStatus(PsnCommunicator source, int resourceId);
        void onFinished(PsnCommunicator source, List<Friend> friends);
        void onError(PsnCommunicator source, int resourceId, Throwable t);
    }
}
